package com.alogic.validator;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;

import com.alogic.load.Loadable;
import com.anysoft.util.Configurable;
import com.anysoft.util.JsonTools;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import com.anysoft.util.XMLConfigurable;
import com.anysoft.util.XmlElementProperties;
import com.anysoft.util.XmlTools;

/**
 * 验证器接口
 * @author yyduan
 * @since 1.6.12.11 [20181206 duanyy] <br>
 *
 * @version 1.6.13.17 [20200923 duanyy] <br>
 * - 优化validator接口
 *
 * @version 1.6.13.25 [20201110 duanyy] <br>
 * - 修复validator的问题
 */
public interface Validator extends Loadable{
	/**
	 * 缺省的结果代码
	 */
	public final static String DFT_CODE = "clnt.e2000";

	/**
	 * 缺省的结果原因
	 */
	public final static String DFT_MESSAGE = "";

	/**
	 * 校验通过时的代码
	 */
	public final static String OK_CODE = "core.ok";

	/**
	 * 校验
	 * @param value 校验值
	 * @param ctx 上下文
	 * @param throwException 以异常的形式抛出
	 * @return 是否通过
	 */
	public boolean check(String value,Properties ctx,boolean throwException);

	/**
	 * 校验
	 * @param value 校验值
	 * @param ctx 上下文
	 * @param listener 校验监听器
	 * @return 是否通过
	 */
	public boolean check(String value,Properties ctx,Listener listener);

	/**
	 * 获取结果代码
	 * @param ctx 上下文
	 * @return 结果代码
	 */
	public String getCode(Properties ctx);

	/**
	 * 获取结果说明
	 * @param ctx 上下文
	 * @return 结果说明
	 */
	public String getMessage(Properties ctx);

	/**
	 * 监听器
	 */
	public static interface Listener {
		boolean result(boolean pass,String value,Validator validator,Properties ctx);
	}
	
	/**
	 * 虚基类
	 * @author yyduan
	 *
	 */
	public static abstract class Abstract implements Validator,XMLConfigurable,Configurable{
		
		/**
		 * a logger of slf4j
		 */
		protected static final Logger LOG = LoggerFactory.getLogger(Validator.class);
		/**
		 * id
		 */
		protected String id;

		/**
		 * 数据加载时间戳
		 */
		protected long timestamp = System.currentTimeMillis();
		
		/**
		 * 数据的生存周期:30分钟
		 */
		public static final long TTL = 30 * 60 * 1000L;

		protected String $message = DFT_MESSAGE;
		protected String $code = DFT_CODE;

		protected boolean reject = true;
		protected int score = 0;
				
		@Override
		public String getId() {
			return id;
		}

		@Override
		public long getTimestamp() {
			return timestamp;
		}
		
		@Override
		public boolean isExpired() {
			return System.currentTimeMillis() - timestamp > TTL;
		}
	
		@Override
		public void expire(){
			timestamp = timestamp - TTL;
		}

		@Override
		public void report(Element xml) {
			if (xml != null){
				XmlTools.setString(xml, "module", getClass().getName());
				XmlTools.setString(xml,"id",getId());
			}
		}

		@Override
		public void report(Map<String, Object> json) {
			if (json != null){
				JsonTools.setString(json,"module",getClass().getName());
				JsonTools.setString(json,"id",getId());
			}
		}

		@Override
		public void configure(Properties p) {
			id = PropertiesConstants.getString(p,"id",id);
			$code = PropertiesConstants.getRaw(p,"code",$code);
			$message = PropertiesConstants.getRaw(p,"message",$message);
		}

		@Override
		public void configure(Element e, Properties p) {
			XmlElementProperties props = new XmlElementProperties(e,p);
			configure(props);
		}

		@Override
		public String getMessage(Properties ctx) {
			return PropertiesConstants.transform(ctx,$message,DFT_MESSAGE);
		}

		@Override
		public String getCode(Properties ctx) {
			return PropertiesConstants.transform(ctx,$code,DFT_CODE);
		}
	}
}
